package main

const DefaultTemplate = `
var _ = model.PH
var _ = msg.PH

{{range .Enums}}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// enum [{{.Name}}] begin

{{if .Comment}}/*
{{.Comment}}
*/{{end}}

var {{.Name}}_Slice = []int32{
	{{range .Values}}{{.Value}},
	{{end}}
}

func {{.Name}}_Len() int {
	return len({{.Name}}_Slice)
}

{{if .Enable0}}
func Check_{{.Name}}_I(value int32) bool {
	if _, ok := {{.Name}}_name[value]; ok {
		return true
	}
	return false
}
{{else}}
func Check_{{.Name}}_I(value int32) bool {
	if _, ok := {{.Name}}_name[value]; ok && value != 0 {
		return true
	}
	return false
}
{{end}}

func Check_{{.Name}}(value {{.Name}}) bool {
	return Check_{{.Name}}_I(int32(value))
}

func Each_{{.Name}}(f func({{.Name}}) bool) {
	for _, value := range {{.Name}}_Slice {
		if !f({{.Name}}(value)) {
			break
		}
	}
}

func Each_{{.Name}}_I(f func(int32) bool) {
	for _, value := range {{.Name}}_Slice {
		if !f(value) {
			break
		}
	}
}
// enum [{{.Name}}] end
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
{{end}}

{{range .Messages}}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// message [{{.Name}}] begin
func New_{{.Name}}() *{{.Name}} {
	m := &{{.Name}}{
{{range .Fields}}
    {{if (eq .DescriptorProtoType "message") }}
        {{if not .IsRepeated}}
            {{if .Required}}
                {{$packageName := SplitPackageName .GoTypeToName}}
                {{if $packageName}}
                    {{$tYpE := SplitType .GoTypeToName}}
                    {{.Name}}: {{$packageName}}.New_{{$tYpE}}(),
                {{else}}
                    {{.Name}}: New_{{.GoTypeToName}}(),
                {{end}}
            {{end}}
        {{else}}
            {{if .Required}}
                {{.Name}}: {{.GoType}}{},
            {{end}}
        {{end}}
    {{else}}
        {{if .DefaultValue}}
            {{if not (eq .DescriptorProtoType "bytes")}}
                {{.Name}}: {{.DefaultValue}},
            {{end}}
        {{end}}
    {{end}}
{{end}}
	}
	return m
}

func (m *{{.Name}}) ResetEx() {
{{range .Fields}}
	{{if .IsRepeated}}
        {{if .IsMessage}}
            {{if .IsMap}}
                {{if and (not .ValueField.IsScalar) (not .ValueField.IsString) (not .ValueField.IsEnum)}}
                    {{if (ne .ValueType "[]byte")}}
                        for _, v := range m.{{.Name}} {
                            {{$packageName := SplitPackageName .ValueTypeToName}}
                            {{if $packageName}}
                                {{$tYpE := SplitType .ValueTypeToName}}
                                {{$packageName}}.Put_{{$tYpE}}(v)
                            {{else}}
                                Put_{{.ValueTypeToName}}(v)
                            {{end}}
                        }
                    {{end}}
                {{end}}
	        {{else}}
                for _, e := range m.{{.Name}} {
                    {{$packageName := SplitPackageName .GoTypeToName}}
                    {{if $packageName}}
                        {{$tYpE := SplitType .GoTypeToName}}
                        {{$packageName}}.Put_{{$tYpE}}(e)
                    {{else}}
                        Put_{{.GoTypeToName}}(e)
                    {{end}}
                }
            {{end}}
        {{end}}
        {{if .Required}}
            m.{{.Name}} = {{.GoType}}{}
        {{else}}
            m.{{.Name}} = nil
        {{end}}
	{{else}}
	    {{if .DefaultValue}}
	        {{if not (eq .DescriptorProtoType "bytes")}}
	            m.{{.Name}} = {{.DefaultValue}}
	        {{end}}
	    {{else}}
	        {{if or (eq .DescriptorProtoType "int32") (eq .DescriptorProtoType "uint32") (eq .DescriptorProtoType "int64") (eq .DescriptorProtoType "uint64") }}
                m.{{.Name}} = 0
            {{end}}
            {{if or (eq .DescriptorProtoType "sint32") (eq .DescriptorProtoType "sint64") (eq .DescriptorProtoType "fixed32") (eq .DescriptorProtoType "fixed64") (eq .DescriptorProtoType "enum")}}
                m.{{.Name}} = 0
            {{end}}
            {{if or (eq .DescriptorProtoType "bool")}}
                m.{{.Name}} = false
            {{end}}
            {{if or (eq .DescriptorProtoType "string")}}
                m.{{.Name}} = ""
            {{end}}
            {{if or (eq .DescriptorProtoType "double") (eq .DescriptorProtoType "float")}}
                m.{{.Name}} = 0.0
            {{end}}
	    {{end}}
        {{if or (eq .DescriptorProtoType "bytes") }}
            {{if .Required}}
                m.{{.Name}} = []byte{}
            {{else}}
                m.{{.Name}} = nil
            {{end}}
        {{end}}
        {{if or (eq .DescriptorProtoType "message") }}
            {{if .Required}}
                if m.{{.Name}} != nil {
                    m.{{.Name}}.ResetEx()
                } else {
                    {{$packageName := SplitPackageName .GoTypeToName}}
                    {{if $packageName}}
                        {{$tYpE := SplitType .GoTypeToName}}
                        m.{{.Name}} = {{$packageName}}.Get_{{$tYpE}}()
                    {{else}}
                        m.{{.Name}} = Get_{{.GoTypeToName}}()
                    {{end}}
                }
            {{else}}
                if m.{{.Name}} != nil {
                    {{$packageName := SplitPackageName .GoTypeToName}}
                    {{if $packageName}}
                        {{$tYpE := SplitType .GoTypeToName}}
                        {{$packageName}}.Put_{{$tYpE}}(m.{{.Name}})
                    {{else}}
                        Put_{{.GoTypeToName}}(m.{{.Name}})
                    {{end}}
                    m.{{.Name}} = nil
                }
            {{end}}
        {{end}}
	{{end}}
{{end}}
}

func (m *{{.Name}}) Clone() *{{.Name}} {
	if m == nil {
		return nil
	}
    n := Get_{{.Name}}()
	deriveDeepCopy{{.Name}}(n, m)
	return n
}

{{if .ID}}
func ({{.Name}}) RPC() {
}

func ({{.Name}}) MessageID() rpc.MessageID {
	return {{.ID}}
}

func {{.Name}}_MessageID() rpc.MessageID {
	return {{.ID}}
}

func ({{.Name}}) MessageName() string {
	return "{{.Name}}"
}

func {{.Name}}_MessageName() string {
	return "{{.Name}}"
}

func ({{.Name}}) ResponseMessageID() rpc.MessageID {
{{if .Response}}
	return {{.Response}}_MessageID()
{{else}}
	return 0
{{end}}
}

func {{.Name}}_ResponseMessageID() rpc.MessageID {
{{if .Response}}
	return {{.Response}}_MessageID()
{{else}}
	return 0
{{end}}
}

{{end}}

{{if .Response}}
func Request_{{.Response}}(pid *PID, send *{{.Name}}) (*{{.Response}}, error) {
	return Request_{{.Response}}_T(pid, send, {{.ResponseTimeout}} * time.Millisecond)
}

func Request_{{.Response}}_T(pid *PID, send *{{.Name}}, timeout time.Duration) (*{{.Response}}, error) {
	if pid == nil {
		return nil, fmt.Errorf("pid is nil")
	}
	f := actor.RootContext.RequestFuture(pid.ToReal(), send, timeout)
	iRecv, err := f.Result()
	if err != nil {
		return nil, err
	}
	recv, ok := iRecv.(*{{.Response}})
	if !ok {
		return nil, fmt.Errorf("recv %#v is not {{.Response}}", recv)
	}
	return recv, nil
}
{{end}}

var g_{{.Name}}_Pool = sync.Pool{}

func Get_{{.Name}}() *{{.Name}} {
	m, ok := g_{{.Name}}_Pool.Get().(*{{.Name}})
	if !ok {
		m = New_{{.Name}}()
	} else {
		if m == nil {
			m = New_{{.Name}}()
		} else {
			m.ResetEx()
		}
	}
	return m
}

func Put_{{.Name}}(i interface{}) {
	if m, ok := i.(*{{.Name}}); ok && m != nil {
		g_{{.Name}}_Pool.Put(i)
	}
}

{{if .ID}}
func init() {
	Protocol.Register(
		&{{.Name}}{},
		func() rpc.IMessage { return Get_{{.Name}}() },
		func(msg rpc.IMessage) { Put_{{.Name}}(msg) },
	)
}
{{end}}
// message [{{.Name}}] end
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
{{end}}
`
